/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package lucava.importer.java;

import java.util.Iterator;
import java.util.List;
import lucava.metamodel.java.Attribute;
import lucava.metamodel.java.ICommentableEntity;
import lucava.metamodel.java.IVisibleEntity;
import lucava.metamodel.java.MetaClasse;
import lucava.metamodel.java.MetaClassifier;
import lucava.metamodel.java.Methode;
import lucava.metamodel.java.type.MetaType;
import lucava.util.StringUtils;
import org.jdom2.Element;

/**
 *
 * @author glenn
 */
class XmlClassElementImporter implements IXmlElementImporter {

    private MetaClasse classElmt;

    /**
     * Build des différents types de noeuds qui compose une classe
     *
     * @param xmlElement
     * @return
     */
    @Override
    public MetaClassifier load(Element xmlElement) {

        classElmt = new MetaClasse();
        classElmt.setName(xmlElement.getAttributeValue("name"));

        this.buildStereotypes(xmlElement.getChildren("stereotype"));
        this.buildComments(classElmt, xmlElement.getChildren("comment"));
        this.buildAttributes(xmlElement.getChildren("attribute"));
        this.buildMethods(xmlElement.getChildren("method"));

        this.buildExtends(xmlElement.getChildren("extends"));
        this.buildImplements(xmlElement.getChildren("implements"));

        this.buildAssociations(xmlElement.getChildren("association"));
        this.buildAggregations(xmlElement.getChildren("aggregation"));
        this.buildCompositions(xmlElement.getChildren("composition"));
        this.buildDependencies(xmlElement.getChildren("dependency"));

        return classElmt;
    }

    private void buildStereotypes(List<Element> children) {
        Iterator<Element> elmtIt = children.iterator();
        while (elmtIt.hasNext()) {
            Element child = elmtIt.next();
            classElmt.setAbstract(child.getAttributeValue("name").equals("abstract"));
            classElmt.setFinal(child.getAttributeValue("name").equals("final"));
        }
    }

    private void buildComments(ICommentableEntity elmt, List<Element> children) {
        Iterator<Element> elmtIt = children.iterator();
        while (elmtIt.hasNext()) {
            Element child = elmtIt.next();
            elmt.addComment(child.getAttributeValue("text"));
        }
    }

    private void buildAttributes(List<Element> children) {
        Iterator<Element> elmtIt = children.iterator();
        while (elmtIt.hasNext()) {
            Element child = elmtIt.next();
            Attribute attr = buildAttribute(child);
            classElmt.addAttribute(attr);
        }
    }

    private Attribute buildAttribute(Element child) {
        String name = child.getAttributeValue("name");
        if (name == null) {
            name = StringUtils.addArticleTo(child.getAttributeValue("type"));
        }

        String card = child.getAttributeValue("targetCard");
        if (card == null) {
            card = "1";
        }

        Attribute attr = new Attribute(
                new MetaType(child.getAttributeValue("type")),
                StringUtils.toCamelCase(name), card);

        this.buildUmlVisibility(attr, child.getAttributeValue("visibility"));
        this.buildComments(attr, child.getChildren("comment"));

        return attr;

    }

    private void buildMethods(List<Element> children) {
        Iterator<Element> elmtIt = children.iterator();
        while (elmtIt.hasNext()) {
            Element child = elmtIt.next();

            Methode meth = new Methode();
            meth.getSignature().setName(child.getAttributeValue("name"));
            meth.getSignature().setReturnType(
                    new MetaType(child.getAttributeValue("type")));
            this.buildUmlVisibility(meth, child.getAttributeValue("visibility"));
            this.buildComments(meth, child.getChildren("comment"));
            classElmt.addMethod(meth);


        }
    }

    private void buildAssociations(List<Element> children) {
        Iterator<Element> elmtIt = children.iterator();
        while (elmtIt.hasNext()) {
            Element child = elmtIt.next();

            Attribute attr = buildAttribute(child);
            attr.setProperty("association", "simple");
            attr.setProperty("directionnal", child.getAttributeValue("directional"));

            classElmt.addAttribute(attr);
        }
    }

    private void buildAggregations(List<Element> children) {
        Iterator<Element> elmtIt = children.iterator();
        while (elmtIt.hasNext()) {
            Element child = elmtIt.next();
            Attribute attr = buildAttribute(child);
            attr.setProperty("association", "aggregation");
            attr.setProperty("directionnal", child.getAttributeValue("directional"));
            classElmt.addAttribute(attr);
        }
    }

    private void buildCompositions(List<Element> children) {
        Iterator<Element> elmtIt = children.iterator();
        while (elmtIt.hasNext()) {
            Element child = elmtIt.next();
            Attribute attr = buildAttribute(child);
            attr.setProperty("association", "composition");
            attr.setProperty("directionnal", child.getAttributeValue("directional"));
            classElmt.addAttribute(attr);
        }
    }

    private void buildDependencies(List<Element> children) {
        Iterator<Element> elmtIt = children.iterator();
        while (elmtIt.hasNext()) {
            elmtIt.next();
            //@TODO dependencies
        }
    }

    private void buildUmlVisibility(IVisibleEntity entity, String value) {

        if (value == null) {
            entity.setProtected();
        } else if (value.equals("+")) {
            entity.setPrivate();
        } else if (value.equals("-")) {
            entity.setPublic();
        } else if (value.equals("#")) {
            entity.setProtected();
        } else {
            entity.setProtected();
        }
    }

    private void buildExtends(List<Element> children) {
        Iterator<Element> elmtIt = children.iterator();
        while (elmtIt.hasNext()) {
            Element child = elmtIt.next();
            classElmt.setExtends(child.getAttributeValue("class"));
        }
    }

    private void buildImplements(List<Element> children) {
        Iterator<Element> elmtIt = children.iterator();
        while (elmtIt.hasNext()) {
            Element child = elmtIt.next();
            classElmt.addImplements(child.getAttributeValue("class"));
        }
    }
}
